Skip to content

Bring targets out of alerts #1353

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 2, 2025
Merged

Conversation

parmesant
Copy link
Contributor

@parmesant parmesant commented Jun 18, 2025

Adds CRUD operations for targets

TODO-

  • Storage of targets depending upon RBAC discussion
  • Modify alerts to use targets using ID (AlertConfig update)

Fixes #XXXX.

Description


This PR has:

  • been tested to ensure log ingestion and log query works.
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added documentation for new or modified features or behaviors.

Summary by CodeRabbit

  • New Features

    • Introduced RESTful API endpoints for managing alert targets, including creating, listing, retrieving, updating, and deleting targets.
    • Added unique identifiers and names to alert targets for precise identification.
    • Enabled asynchronous, concurrent management and validation of alert targets.
    • Added support for loading, persisting, and deleting targets in storage with concurrency safety.
    • Added new error responses for invalid, duplicate, or in-use target configurations.
    • Implemented asynchronous validation and error handling during alert creation and modification.
  • Bug Fixes

    • Improved error handling for invalid target IDs with clear error messages.
  • Chores

    • Updated internal alert configuration to reference targets by ID, improving performance and maintainability.
    • Added new constants for target-related storage directories.

Adds CRUD operations for targets

TODO-
- Storage of targets depending upon RBAC discussion
- Modify alerts to use targets using ID (AlertConfig update)
Copy link
Contributor

coderabbitai bot commented Jun 18, 2025

Walkthrough

This update introduces a new asynchronous, ID-based system for managing alert targets. Targets are now referenced by unique ULIDs instead of embedded objects, with a global concurrent registry for CRUD operations. New HTTP endpoints enable RESTful management of targets with RBAC authorization. Persistent storage integration supports loading and saving target configurations.

Changes

File(s) Change Summary
src/alerts/mod.rs Changed alert target fields from Vec<Target> to Vec<Ulid>, replaced synchronous conversions with async methods, added async validation on target IDs, and introduced new error variants for invalid or duplicate targets.
src/alerts/target.rs Added global static TARGETS registry with async, concurrency-safe CRUD operations and persistent storage integration; added id: Ulid and name: String fields to Target and TargetVerifier; added async duplicate detection validation.
src/handlers/http/alerts.rs Updated alert creation handler to use async conversion from AlertRequest to AlertConfig with error propagation.
src/handlers/http/targets.rs New file: Implements async RESTful HTTP handlers for creating, listing, retrieving, updating, and deleting targets by ULID with validation and error handling.
src/handlers/http/mod.rs Added public module declaration for targets.
src/handlers/http/modal/server.rs Added /targets web scope with CRUD endpoints protected by RBAC authorization, registered in main server routes.
src/handlers/http/modal/query_server.rs Registered new get_targets_webscope route in server API setup.
src/storage/mod.rs Added constants SETTINGS_ROOT_DIRECTORY and TARGETS_ROOT_DIRECTORY for organizing target storage directories.
src/storage/object_storage.rs Extended ObjectStorage trait with async method to load targets from storage; added helper function for target JSON file paths.
src/storage/localfs.rs Added SETTINGS_ROOT_DIRECTORY to ignored directories in stream listing methods.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant HTTP_Handler as HTTP Handler (/targets)
    participant TARGETS as TargetConfigs (Registry)
    participant Storage

    Client->>HTTP_Handler: POST /targets (Target JSON)
    HTTP_Handler->>TARGETS: update(target)
    TARGETS->>Storage: Save target to persistent storage
    HTTP_Handler-->>Client: Target created (JSON)

    Client->>HTTP_Handler: GET /targets
    HTTP_Handler->>TARGETS: list()
    TARGETS->>Storage: (on load) get_targets()
    HTTP_Handler-->>Client: List of targets (JSON)

    Client->>HTTP_Handler: GET /targets/{id}
    HTTP_Handler->>TARGETS: get_target_by_id(id)
    HTTP_Handler-->>Client: Target (JSON)
Loading
sequenceDiagram
    participant AlertHandler
    participant TARGETS as TargetConfigs

    AlertHandler->>TARGETS: get_target_by_id(target_id)
    TARGETS-->>AlertHandler: Target object (or error)
    AlertHandler->>Target: validate() / trigger_notifications()
Loading

Suggested reviewers

  • nikhilsinhaparseable

Poem

In the meadow of code where the targets now play,
Each one has a ULID, unique in its way.
With async and storage, they’re easy to find,
And CRUD little bunnies hop gently behind.
RESTful new burrows, the registry grows—
Hooray for the targets, wherever one goes!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b9ed392 and b764f26.

📒 Files selected for processing (1)
  • src/storage/localfs.rs (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: de-sh
PR: parseablehq/parseable#0
File: :0-0
Timestamp: 2025-03-20T15:50:45.435Z
Learning: Pay close attention to code comments for typos and semantic clarity during reviews for the Parseable project.
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • GitHub Check: coverage
  • GitHub Check: Build Default x86_64-pc-windows-msvc
  • GitHub Check: Build Default aarch64-apple-darwin
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
  • GitHub Check: Build Kafka x86_64-unknown-linux-gnu
  • GitHub Check: Build Default x86_64-apple-darwin
  • GitHub Check: Build Kafka aarch64-apple-darwin
  • GitHub Check: Quest Smoke and Load Tests for Distributed deployments
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
🔇 Additional comments (2)
src/storage/localfs.rs (2)

44-44: LGTM: Import addition is correct.

The import of SETTINGS_ROOT_DIRECTORY is necessary for the changes below and follows the existing import pattern.


340-340: LGTM: Settings directory properly excluded from stream listings.

Adding SETTINGS_ROOT_DIRECTORY to both ignore lists is correct since the .settings directory contains metadata (like targets) rather than log streams, and should be excluded from stream discovery.

Also applies to: 361-361

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Alerts creation will require the ULID of the target instead of the target body
@parmesant parmesant marked this pull request as ready for review June 30, 2025 01:40
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (4)
src/handlers/http/modal/server.rs (1)

258-275: Consider using target-specific RBAC actions for clarity.

The targets webscope implementation is well-structured with proper RESTful endpoints. However, using alert-related actions (GetAlert, PutAlert, DeleteAlert) for target operations might be confusing from a permissions perspective.

Consider introducing target-specific RBAC actions like GetTarget, PutTarget, DeleteTarget for better clarity and separation of concerns, unless the current approach is intentional due to the close relationship between alerts and targets.

src/storage/object_storage.rs (1)

998-1002: Address the TODO for distributed mode consistency.

The TODO comment indicates this needs to be updated for distributed mode, similar to alert_json_path. Consider tracking this technical debt to ensure both functions are updated together when implementing distributed mode support.

Would you like me to create an issue to track updating both alert_json_path and target_json_path for distributed mode?

src/handlers/http/targets.rs (2)

39-39: Remove or update the misleading comment.

The comment "add to the map" doesn't make sense for a list operation.

-    // add to the map

65-65: Fix typo in comment.

-    // esnure that the supplied target id is assigned to the target config
+    // ensure that the supplied target id is assigned to the target config
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97e5d42 and 484a0c7.

📒 Files selected for processing (9)
  • src/alerts/mod.rs (7 hunks)
  • src/alerts/target.rs (4 hunks)
  • src/handlers/http/alerts.rs (1 hunks)
  • src/handlers/http/mod.rs (1 hunks)
  • src/handlers/http/modal/query_server.rs (1 hunks)
  • src/handlers/http/modal/server.rs (3 hunks)
  • src/handlers/http/targets.rs (1 hunks)
  • src/storage/mod.rs (1 hunks)
  • src/storage/object_storage.rs (4 hunks)
🧰 Additional context used
🧠 Learnings (3)
src/handlers/http/alerts.rs (1)
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1346
File: src/handlers/http/health_check.rs:81-90
Timestamp: 2025-06-16T02:04:58.990Z
Learning: In the shutdown function in src/handlers/http/health_check.rs, the design approach is to log errors from sync operations rather than propagate them. This is intentional because the shutdown function is called on SIGTERM/SIGINT signals, and the goal is to perform best-effort cleanup (syncing pending files to object storage) while allowing the shutdown to proceed regardless of sync failures. Logging provides debugging information without blocking the shutdown process.
src/handlers/http/modal/server.rs (1)
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:0-0
Timestamp: 2025-05-01T10:27:56.858Z
Learning: The `add_tile()` function in `src/handlers/http/users/dashboards.rs` should use `get_dashboard_by_user(dashboard_id, &user_id)` instead of `get_dashboard(dashboard_id)` to ensure proper authorization checks when modifying a dashboard.
src/storage/object_storage.rs (2)
Learnt from: de-sh
PR: parseablehq/parseable#1185
File: src/handlers/http/logstream.rs:255-261
Timestamp: 2025-02-14T09:49:25.818Z
Learning: In Parseable's logstream handlers, stream existence checks must be performed for both query and standalone modes. The pattern `!PARSEABLE.streams.contains(&stream_name) && (PARSEABLE.options.mode != Mode::Query || !PARSEABLE.create_stream_and_schema_from_storage(&stream_name).await?)` ensures proper error handling in both modes.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1263
File: src/handlers/http/ingest.rs:300-310
Timestamp: 2025-03-26T06:44:53.362Z
Learning: In Parseable, every stream is always associated with a log_source - no stream can exist without a log_source. For otel-traces and otel-metrics, strict restrictions are implemented where ingestion is rejected if a stream already has a different log_source format. However, regular logs from multiple log_sources can coexist in a single stream.
🧬 Code Graph Analysis (2)
src/handlers/http/modal/query_server.rs (1)
src/handlers/http/modal/server.rs (1)
  • get_targets_webscope (258-275)
src/alerts/target.rs (9)
src/storage/mod.rs (2)
  • new (183-185)
  • new (196-202)
src/alerts/mod.rs (7)
  • new (113-119)
  • new (154-166)
  • new (177-183)
  • load (847-870)
  • update (902-904)
  • delete (944-951)
  • validate (579-632)
src/handlers/http/modal/mod.rs (1)
  • new (256-278)
src/handlers/http/targets.rs (3)
  • update (55-80)
  • list (38-43)
  • delete (83-92)
src/handlers/http/logstream.rs (2)
  • list (82-102)
  • delete (47-80)
src/parseable/streams.rs (1)
  • v (611-613)
src/handlers/http/modal/query/querier_logstream.rs (1)
  • delete (52-110)
src/handlers/http/modal/ingest/ingestor_logstream.rs (1)
  • delete (60-79)
src/alerts/alerts_utils.rs (1)
  • value (413-413)
🔇 Additional comments (8)
src/storage/mod.rs (1)

62-62: LGTM! Consistent with existing patterns.

The new TARGETS_ROOT_DIRECTORY constant follows the established naming convention and placement pattern used by other metadata directory constants in this module.

src/handlers/http/mod.rs (1)

50-50: LGTM! Proper module integration.

The targets module declaration follows the established pattern and maintains alphabetical ordering with other HTTP handler modules.

src/handlers/http/modal/query_server.rs (1)

72-72: LGTM! Proper service integration.

The targets webscope is correctly registered in the QueryServer route configuration, following the same pattern as other service registrations.

src/handlers/http/alerts.rs (1)

51-51: Verify async conversion of AlertRequest → AlertConfig across the codebase

Our search for other AlertRequest.into().await? or AlertConfig::from(AlertRequest) patterns didn’t surface any additional occurrences. To be safe:

• Manually scan for any other AlertRequestAlertConfig conversions (e.g. via

rg "AlertRequest" && rg "AlertConfig"

) and update them to the new async form if needed.
• Ensure all callers now await the conversion and properly handle errors.
• Benchmark the alert handler under realistic loads to catch any unexpected latency introduced by the async lookup.

src/handlers/http/modal/server.rs (2)

29-29: LGTM! Proper module import.

The targets module import is correctly placed with other handler imports.


91-91: LGTM! Consistent service registration.

The targets webscope service registration follows the established pattern and is properly integrated with other services.

src/storage/object_storage.rs (1)

427-444: LGTM! Consistent implementation with get_alerts().

The implementation follows the same pattern as the existing get_alerts() method, which is good for consistency.

src/alerts/target.rs (1)

44-99: Well-structured concurrent target management.

The TargetConfigs implementation properly handles concurrent access with async RwLock and provides a clean API for target management.

@parmesant parmesant force-pushed the targets-separation branch from 329b787 to cd363c2 Compare June 30, 2025 01:46
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
src/alerts/target.rs (1)

128-141: Implementation differs from past review suggestion.

A past review suggested implementing HTTP health checks for target validation, but this implementation checks for duplicates instead. The current approach is valid but differs from the original suggestion.

The duplicate checking logic addresses a different concern than target liveness validation.

🧹 Nitpick comments (1)
src/alerts/target.rs (1)

55-64: Consider error handling for storage operations.

The get_targets() call uses unwrap_or_default() which silently ignores storage errors. Consider logging storage failures for debugging purposes.

-        for alert in store.get_targets().await.unwrap_or_default() {
+        let targets = match store.get_targets().await {
+            Ok(targets) => targets,
+            Err(e) => {
+                warn!("Failed to load targets from storage: {}", e);
+                Vec::new()
+            }
+        };
+        for alert in targets {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd363c2 and 69dbdd7.

📒 Files selected for processing (3)
  • src/alerts/mod.rs (7 hunks)
  • src/alerts/target.rs (4 hunks)
  • src/handlers/http/targets.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/handlers/http/targets.rs
  • src/alerts/mod.rs
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: Build Kafka aarch64-apple-darwin
  • GitHub Check: Build Kafka x86_64-unknown-linux-gnu
  • GitHub Check: Build Default aarch64-apple-darwin
  • GitHub Check: Build Default x86_64-apple-darwin
  • GitHub Check: coverage
  • GitHub Check: Build Default x86_64-pc-windows-msvc
  • GitHub Check: Build Default x86_64-unknown-linux-gnu
  • GitHub Check: Build Default aarch64-unknown-linux-gnu
  • GitHub Check: Quest Smoke and Load Tests for Standalone deployments
  • GitHub Check: Quest Smoke and Load Tests for Distributed deployments
🔇 Additional comments (4)
src/alerts/target.rs (4)

30-31: LGTM: Appropriate imports added.

The itertools::Itertools and once_cell::sync::Lazy imports are correctly added to support the new functionality.


44-46: Global static is well-implemented.

The lazy initialization with RwLock<HashMap<Ulid, Target>> provides thread-safe access with good read performance for the target registry.


123-124: Well-implemented ID field addition.

The id field with Ulid::new default provides unique identification for targets. The serde configuration correctly handles serialization.


276-277: Consistent ID handling in TargetVerifier.

The ID field is properly added to TargetVerifier and correctly transferred during conversion to Target.

Also applies to: 310-310

@parmesant
Copy link
Contributor Author

Need to update Quest to reflect the changes. Will send a PR there as well

@parmesant parmesant force-pushed the targets-separation branch 2 times, most recently from c511001 to 9ccb849 Compare June 30, 2025 08:44
@parmesant parmesant force-pushed the targets-separation branch from e6fe12f to cd39b98 Compare June 30, 2025 13:38
coderabbitai[bot]
coderabbitai bot previously approved these changes Jul 1, 2025
Copy link
Contributor

@nikhilsinhaparseable nikhilsinhaparseable left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good

@nitisht nitisht merged commit 7726912 into parseablehq:main Jul 2, 2025
14 checks passed
@parmesant parmesant deleted the targets-separation branch July 3, 2025 08:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants